package Element;

import java.awt.*;
import java.awt.geom.*;

import Element.Geom.*;
import DistSys.*;

public class Txfm extends AbsElem implements Cloneable {
    public static AbsElem objActiveTemp;  //a developer's version of ActiveTemplate

    public Txfm(){ }

    public Object clone(){
        Txfm created = new Txfm();
        this.copyTo(created); // copy AbsElem attributes to created
        //created.setDftTemp(this.getDftTempName());
        //created.rel  = (ReliaInd) (this.rel.clone());
        //created.ckt  = (CktLaw) (this.ckt.clone() );
        created.geom = (TwoNodeElemGeom) (((TwoNodeElemGeom)this.geom).clone());
        return created;
    }

    public int getType() {
        return (isTemplate() ? SysConst.TEMPLTYPE_TRANSFORMER :
            SysConst.TYPE_TRANSFORMER);
    }

    public void draw(Graphics2D g2, double dist, double theta) {
        int x1 = geom.x1, y1 = geom.y1, x2 = geom.x2, y2 = geom.y2;

        Point A = new Point(), B = new Point(), C = new Point();
        A.x = x1 + (int)(dist * Math.cos(theta)/4);
        A.y = y1 + (int)(dist * Math.sin(theta)/4);
        B.x = x1 + (int)(dist * Math.cos(theta)*3/4);
        B.y = y1 + (int)(dist * Math.sin(theta)*3/4);
        C.x = (A.x + B.x)/2;
        C.y = (A.y + B.y)/2;

        g2.drawLine(x1,y1, A.x,A.y);     // don't rotate the handle line
        g2.drawLine(B.x,B.y, x2,y2);

        int tmp = (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y);
        double r = (1.0/4) * Math.sqrt( (double)tmp );
        int dd = (int)(2*r);      // diameter of the half circle

        AffineTransform t = geom.t;
        t.setToRotation(theta, C.x, C.y);
        g2.transform(t);

        BasicStroke dftBS = (BasicStroke) g2.getStroke();
        BasicStroke newBS = new BasicStroke(2*dftBS.getLineWidth(),
                                            dftBS.getEndCap(),
                                            dftBS.getLineJoin(),
                                            dftBS.getMiterLimit(),
                                            dftBS.getDashArray(),  // customized dash
                                            dftBS.getDashPhase());
        g2.setStroke(newBS);

        g2.drawArc ((int)(C.x - 3*r), (int)(C.y-4*r), dd, dd,  -90, 180 );
        g2.drawArc ((int)(C.x - 3*r), (int)(C.y-2*r), dd, dd,  -90, 180 );
        g2.drawArc ((int)(C.x - 3*r), (int)(C.y    ), dd, dd,  -90, 180 );
        g2.drawArc ((int)(C.x - 3*r), (int)(C.y+2*r), dd, dd,  -90, 180 );

        g2.setStroke(dftBS);

        g2.drawArc ((int)(C.x + 1*r), (int)(C.y-4*r), dd, dd,  90, 180 );
        g2.drawArc ((int)(C.x + 1*r), (int)(C.y-2*r), dd, dd,  90, 180 );
        g2.drawArc ((int)(C.x + 1*r), (int)(C.y    ), dd, dd,  90, 180 );
        g2.drawArc ((int)(C.x + 1*r), (int)(C.y+2*r), dd, dd,  90, 180 );
    }

    /**
     * Returns whether the data field with the given index "makes sense" for
     * this element type or not.
     *
     * @param index  a <code>int</code> specifying the index.
     *
     * @return  <code>true</code> if the data field "makes sense",
     *          <code>false</code> otherwise
     */
    public boolean getDataExists(int index) {
        // A switch is used here to be independent of the
        // AbsElem.DATA_* constant's real values.
        switch(index) {
            case AbsElem.DATA_ZONE:
            case AbsElem.DATA_LAYER:
            case AbsElem.DATA_RATED_POWER:
            case AbsElem.DATA_RATED_CURR:
            case AbsElem.DATA_ZONE_BUFFER0:
            case AbsElem.DATA_ZONE_BUFFER2:
            case AbsElem.DATA_ZONE_BUFFER4:
            case AbsElem.DATA_ZONE_BUFFER1:
            case AbsElem.DATA_ZONE_BUFFER3:
            case AbsElem.DATA_TEMP_FAULT:
            case AbsElem.DATA_SUST_FAULT:
            case AbsElem.DATA_OPEN_CKT:
            case AbsElem.DATA_MTTR:
            case AbsElem.DATA_VOLT_SAG_LEVEL:
            case AbsElem.DATA_RESISTANCE:
            case AbsElem.DATA_REACTANCE:
            case AbsElem.DATA_SHUNT_COND:
            case AbsElem.DATA_SHUNT_SUCEP:
            case AbsElem.DATA_CAPITAL_COST:
            case AbsElem.DATA_OM_COST:
            case AbsElem.DATA_TXFM_RATIO:
            case AbsElem.DATA_TAP_RATIO:
            case AbsElem.DATA_NUM_BOOST:
            case AbsElem.DATA_NUM_BUCK:
            case AbsElem.DATA_BOOST_TRIG:
            case AbsElem.DATA_BUCK_TRIG:
            case AbsElem.DATA_FONT_SIZE:
            case AbsElem.DATA_IN_OPT_LIB:
            case AbsElem.DATA_MAINT_DUR:
            case AbsElem.DATA_MAINT_RATE:
            case AbsElem.DATA_OPTIMIZABLE:
            case AbsElem.DATA_PHASE:
            case AbsElem.DATA_STUDY_AREA:
            case AbsElem.DATA_UPGRADE_COST:
            case AbsElem.DATA_YEAR:
                return true;
            default:
                return false;
        }
    }

    /**
     * Returns whether the result field with the given index "makes sense" for
     * this element type or not.
     *
     * @param index  a <code>int</code> specifying the index.
     *
     * @return  <code>true</code> if the result field "makes sense",
     *          <code>false</code> otherwise
     */
    public boolean getResultExists(int index) {
        // A switch is used here to be independent of the
        // AbsElem.RES_* constant's real values.
        switch(index) {
            case AbsElem.RES_QUERY_SCORE:
            case AbsElem.RES_QUERY_SCORE_PERC:
            case AbsElem.RES_MOMENT_INT:
            case AbsElem.RES_SUST_INT:
            case AbsElem.RES_OUT_DUR:
            case AbsElem.RES_VOLT_SAGS:
            case AbsElem.RES_CAPA_CONS:
            case AbsElem.RES_CAPA_CONS_KVA:
            case AbsElem.RES_KVA_FLOW:
            case AbsElem.RES_PF:
            case AbsElem.RES_VOLT_MAG:
            case AbsElem.RES_VOLT_ANG:
            case AbsElem.RES_CURR_MAG:
            case AbsElem.RES_CURR_ANG:
            case AbsElem.RES_SHORTCIRC_CURR:
            case AbsElem.RES_VOLT_DROP:
            case AbsElem.RES_CURR_LOADING:
            case AbsElem.RES_KVA_RATING:
            case AbsElem.RES_TAP_POS:
            case AbsElem.RES_MAIFI:
            case AbsElem.RES_SAG:
            case AbsElem.RES_SAIDI:
            case AbsElem.RES_SAIFI:
            case AbsElem.RES_VOLT_MAG_NODE1:
            case AbsElem.RES_VOLT_ANG_NODE1:
            case AbsElem.RES_VOLT_SAGS_ON_TGT:
            case AbsElem.RES_VOLT_SAGS_NODE1:
            case AbsElem.RES_PROTECT_ZONE:
            case AbsElem.RES_SA_MOMENT_INT:
            case AbsElem.RES_SA_SUST_INT:
            case AbsElem.RES_SA_DUR_SI:
            case AbsElem.RES_OLV_MI:
            case AbsElem.RES_OLV_SI:
            case AbsElem.RES_OLV_DUR_SI:
            case AbsElem.RES_UVV_MI:
            case AbsElem.RES_UVV_SI:
            case AbsElem.RES_UVV_DUR_SI:
                return true;
            default:
                return false;
        }
    }
}